/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.transas.zorlog.data.log;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

/**
 *
 * @author amalikov
 */
public class FcsPacketReader extends PacketReader {
	public FcsPacketReader(InputStream in) {
		super(in);
	}

	@Override
	public ByteBuffer getPacket() throws IOException {
		while (true) {
			in.mark(65536);		// remember current position
			
			byte[] t = new byte[5];
			if (in.read(t) != t.length)
				return null;	// end of stream
		
			int size = ByteBuffer.wrap(t).order(ByteOrder.LITTLE_ENDIAN).getShort(1) & 0xFFFF;
			if (size >= 6) {
				byte[] buf = Arrays.copyOf(t, size);
				if ((in.read(buf, 5, size - 5) == (size - 5))
					&& (getCrc(buf, size - 2) == ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).getShort(size - 2)))
					return ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN);
			}

			in.reset();		// return to the remembered position
			in.read();		// skip byte
		}
	}
	
	@Override
	public int getId(ByteBuffer packet) {
		return (int)(packet.get(0) & 0xFF);
	}
	
	/**
	 * Returns the CRC16 value for the given byte array
	 * @param data - array of bytes
	 * @param size - number of bytes
	 */
	private short getCrc(final byte[] data, int size) {
		short crc = (short)0xFFFF;
		
		for (int i = 0; i < size; ++i) {
			crc ^= ((short)data[i]) << 8;
			
			for (int j = 0; j < 8; ++j)
				crc = (short)(((crc & 0x8000) != 0) ? (crc << 1) ^ 0x1021 : (crc << 1));
		}
		
		return crc;
	}
}
